home *** CD-ROM | disk | FTP | other *** search
/ User's Choice Windows CD / User's Choice Windows CD (CMS Software)(1993).iso / misc1 / iv26_w30.zip / SOURCES / SPACE.C < prev    next >
C/C++ Source or Header  |  1992-03-25  |  13KB  |  600 lines

  1. /*
  2.  * Copyright (c) 1987, 1988, 1989 Stanford University
  3.  *
  4.  * Permission to use, copy, modify, distribute, and sell this software and its
  5.  * documentation for any purpose is hereby granted without fee, provided
  6.  * that the above copyright notice appear in all copies and that both that
  7.  * copyright notice and this permission notice appear in supporting
  8.  * documentation, and that the name of Stanford not be used in advertising or
  9.  * publicity pertaining to distribution of the software without specific,
  10.  * written prior permission.  Stanford makes no representations about
  11.  * the suitability of this software for any purpose.  It is provided "as is"
  12.  * without express or implied warranty.
  13.  *
  14.  * STANFORD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
  15.  * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS.
  16.  * IN NO EVENT SHALL STANFORD BE LIABLE FOR ANY SPECIAL, INDIRECT OR
  17.  * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
  18.  * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
  19.  * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION
  20.  * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  21.  */
  22.  
  23. /*
  24.  * Object spaces are objects that manage a collection of other objects.
  25.  */
  26.  
  27. #include <InterViews/catalog.h>
  28. #include <InterViews/connection.h>
  29. #include <InterViews/space.h>
  30. #include <InterViews/packet.h>
  31. #include <InterViews/spaceman.h>
  32. #include <InterViews/stub.h>
  33. #include <InterViews/tagtable.h>
  34. #include <mem.h>
  35. #include <errno.h>
  36. #include <signal.h>
  37. #include <stdio.h>
  38. #include <stdlib.h>
  39. #include <string.h>
  40. //#include <os/ipc.h>
  41. #include <time.h>
  42.  
  43. /*
  44.  * Helper class for object spaces.
  45.  * A messenger handles requests for a particular client.
  46.  */
  47.  
  48. typedef enum { ready, waiting, finished } MessengerState;
  49.  
  50. class Messenger {
  51. private:
  52.     friend class ObjectSpace;
  53.  
  54.     Messenger(ObjectSpace*, Connection*);
  55.     ~Messenger();
  56.  
  57.     MessengerState Run();
  58.     Connection* GetClient () { return client; }
  59.     void SetPending () { pending = true; }
  60.  
  61.     ObjectSpace* space;
  62.     Connection* client;
  63.     boolean pending;    /* buffer contains at least one complete packet */
  64.     char* buffer;    /* buffer of incoming packets */
  65.     int buflen;        /* length of buffer */
  66.     int cur;        /* offset in buffer of current packet */
  67.     int count;        /* number of bytes left in buffer */
  68.     Messenger* next;    /* in dispatcher's list */
  69.     Messenger* prev;
  70.  
  71.     MessengerState ReadData();
  72.     boolean ProcessMessage();
  73.     void GrowBuffer(int);
  74. };
  75.  
  76. /*
  77.  * Create a space without registering it with the space manager.
  78.  */
  79.  
  80. ObjectSpace::ObjectSpace () {
  81.     Init();
  82.     name = nil;
  83.     manager = nil;
  84. }
  85.  
  86. /*
  87.  * Create a space and register it with the space manager under
  88.  * the given name.
  89.  */
  90.  
  91. ObjectSpace::ObjectSpace (const char* str) {
  92.     Init();
  93.     name = strrchr(str, '/');
  94.     if (name == nil) {
  95.     name = str;
  96.     } else {
  97.     ++name;
  98.     }
  99.     manager = new SpaceManager;
  100.     local = new Connection;
  101.     manager->Register(str, local, remote);
  102.     Listen(local);
  103. }
  104.  
  105. ObjectSpace::~ObjectSpace () {
  106.     delete dictionary;
  107.     delete table;
  108. }
  109.  
  110. /*
  111.  * Initialize object space information.
  112.  */
  113.  
  114. void ObjectSpace::Init () {
  115.     dictionary = new Catalog(4096);
  116.     table = new ObjectTable(4096);
  117.     local = nil;
  118.     remote = nil;
  119.     channels = 0;
  120.     maxchannel = 0;
  121.     active.head = nil;
  122.     inactive.head = nil;
  123.     streams = nil;
  124.     /*
  125.      * Ignore SIGPIPE's because they can be caused by writing to a client
  126.      * after the client exits.
  127.      */
  128.     signal(SIGABRT, SIG_IGN);
  129. }
  130.  
  131. /*
  132.  * Add a descriptor to the select mask.
  133.  */
  134.  
  135. void ObjectSpace::Attach (register int ch) {
  136.     channels |= (1 << ch);
  137.     if (ch > maxchannel) {
  138.     maxchannel = ch;
  139.     }
  140. }
  141.  
  142. /*
  143.  * Remove a descriptor from the select mask.
  144.  * This is a bit of a pain because we need to adjust
  145.  * maxchannels in case the removed descriptor was the highest one
  146.  * in the mask.
  147.  */
  148.  
  149. void ObjectSpace::Detach (int ch) {
  150.     channels &= ~(1 << ch);
  151.     if (channels == 0) {
  152.     maxchannel = 0;
  153.     } else {
  154.     while ((channels & (1 << maxchannel)) == 0) {
  155.         --maxchannel;
  156.     }
  157.     }
  158. }
  159.  
  160. /*
  161.  * Start listening to the given connection, assuming it is not nil.
  162.  */
  163.  
  164. void ObjectSpace::Listen (Connection* c) {
  165.     if (c != nil) {
  166.     Attach(c->Descriptor());
  167.     }
  168. }
  169.  
  170. /*
  171.  * Check to see if the given mask indicates that a connection
  172.  * has data pending.
  173.  */
  174.  
  175. boolean ObjectSpace::Ready (int mask, Connection* c) {
  176.     register int d;
  177.  
  178.     d = (1 << c->Descriptor());
  179.     if ((mask & d) != 0) {
  180.     mask &= ~d;
  181.     return true;
  182.     }
  183.     return false;
  184. }
  185.  
  186. /*
  187.  * Check to see if the given mask contains the service connection.
  188.  * If so, add a new client.
  189.  */
  190.  
  191. void ObjectSpace::CheckServer (int mask, Connection* c) {
  192.     if (c != nil && Ready(mask, c)) {
  193.     Connection* nc = c->AcceptClient();
  194.     Listen(nc);
  195.     AddClient(nc);
  196.     }
  197. }
  198.  
  199. /*
  200.  * Start listening to the service connections.
  201.  */
  202.  
  203. void ObjectSpace::StartServer (Connection* here, Connection* there) {
  204.     Listen(here);
  205.     Listen(there);
  206.     local = here;
  207.     remote = there;
  208. }
  209.  
  210. /*
  211.  * Add a messenger to the given queue.
  212.  */
  213.  
  214. void ObjectSpace::Add (register Messenger* m, register MQueue& q) {
  215.     m->next = nil;
  216.     if (q.head == nil) {
  217.     m->prev = nil;
  218.     q.head = m;
  219.     q.tail = m;
  220.     } else {
  221.     m->prev = q.tail;
  222.     q.tail->next = m;
  223.     q.tail = m;
  224.     }
  225. }
  226.  
  227. /*
  228.  * Remove a messenger from the given queue.
  229.  */
  230.  
  231. void ObjectSpace::Remove (register Messenger* m, MQueue& q) {
  232.     if (m->prev == nil) {
  233.     q.head = m->next;
  234.     } else {
  235.     m->prev->next = m->next;
  236.     }
  237.     if (m->next == nil) {
  238.     q.tail = m->prev;
  239.     } else {
  240.     m->next->prev = m->prev;
  241.     }
  242. }
  243.  
  244. /*
  245.  * Disconnect from a given messenger.
  246.  */
  247.  
  248. void ObjectSpace::CloseDown (Messenger* m) {
  249.     Connection* c = m->GetClient();
  250.     Detach(c->Descriptor());
  251.     table->RemoveAll(c);
  252.     delete m;
  253. }
  254.  
  255. /*
  256.  * Default way to add a client is to create a messenger for it.
  257.  * Spaces need to redefine this if they want to treat clients as streams.
  258.  */
  259.  
  260. void ObjectSpace::AddClient (Connection* c) {
  261.     Add(new Messenger(this, c), inactive);
  262. }
  263.  
  264. /*
  265.  * Basic message-handling dispatch loop.
  266.  */
  267.  
  268. void ObjectSpace::Dispatch () {
  269.     register int nready;
  270.     register Messenger* m;
  271.     register Stream* s;
  272.     int rdmask;
  273.  
  274.     m = active.head;
  275.     if (m == nil) {
  276.     do {
  277.         rdmask = channels;
  278.         nready = 0; //select(maxchannel+1, &rdmask, 0, 0, nil);
  279.         if (nready < 0 && errno == EBADF) {
  280.         CheckClients();
  281.         }
  282.     } while (nready < 0);
  283.     CheckServer(rdmask, local);
  284.     CheckServer(rdmask, remote);
  285.     if (rdmask != 0) {
  286.         for (m = inactive.head; m != nil; m = m->next) {
  287.         if (Ready(rdmask, m->GetClient())) {
  288.             m->SetPending();
  289.             Remove(m, inactive);
  290.             Add(m, active);
  291.         }
  292.         }
  293.         for (s = streams; s != nil; s = s->next) {
  294.         if ((rdmask & s->mask) != 0) {
  295.             s->object->ChannelReady(s->channel);
  296.         }
  297.         }
  298.     }
  299.     } else {
  300.     Remove(m, active);
  301.     switch (m->Run()) {
  302.         case ready:
  303.         Add(m, active);
  304.         break;
  305.         case waiting:
  306.         Add(m, inactive);
  307.         break;
  308.         case finished:
  309.         CloseDown(m);
  310.         break;
  311.     }
  312.     }
  313. }
  314.  
  315. /*
  316.  * Poll the inactive clients to see if any have disappeared.
  317.  * This shouldn't really be necessary; we only do it when
  318.  * we get a bad file error from select in Dispatch.
  319.  */
  320.  
  321. void ObjectSpace::CheckClients () {
  322.     register Messenger* m;
  323.     register Messenger* next;
  324.     register int d;
  325.     int rdmask;
  326.     struct tm poll;
  327.  
  328. /*    poll.tm_sec = 0;
  329.     for (m = inactive.head; m != nil; m = next) {
  330.     next = m->next;
  331.     d = m->GetClient()->Descriptor();
  332.     rdmask = 1 << d;
  333.     if (select(d+1, &rdmask, 0, 0, &poll) < 0) {
  334.         Remove(m, inactive);
  335.         CloseDown(m);
  336.     }
  337.     }
  338. */
  339. }
  340.  
  341. /*
  342.  * Default way to handle messages to the space itself.
  343.  */
  344.  
  345. void ObjectSpace::Message (Connection* c, ObjectTag, int op, void* msg, int) {
  346.     register objectspace_Msg* m;
  347.     ObjectStub* s;
  348.  
  349.     m = (objectspace_Msg*)msg;
  350.     switch (op) {
  351.     case objectspace_Find:
  352.         if (dictionary->Find(s, m->name)) {
  353.         table->Add(c, m->tag, s);
  354.         }
  355.         break;
  356.     case objectspace_Clone:
  357.         if (dictionary->Find(s, m->name)) {
  358.         table->Add(c, m->tag, s->Clone());
  359.         }
  360.         break;
  361.     case objectspace_Destroy:
  362.         if (dictionary->Find(s, m->name)) {
  363.         dictionary->UnRegister(m->name);
  364.         Unref(s);
  365.         }
  366.         break;
  367.     default:
  368.         /* ignore op */;
  369.     }
  370. }
  371.  
  372. /*
  373.  * Return the stub associated with a given tag.
  374.  */
  375.  
  376. ObjectStub* ObjectSpace::Map (Connection* client, ObjectTag t) {
  377.     return table->Find(client, t);
  378. }
  379.  
  380. /*
  381.  * Deliver a message to the appropriate stub.  A zero tag
  382.  * by convention means a message to the object space itself.
  383.  */
  384.  
  385. void ObjectSpace::Deliver (
  386.     Connection* client, ObjectTag t, int op, void* msg, int n
  387. ) {
  388.     if (t == 0) {
  389.     Message(client, t, op, msg, n);
  390.     } else {
  391.     ObjectStub* s = Map(client, t);
  392.     if (s == nil) {
  393.         /* bad target tag -- what should we do? */
  394.     } else {
  395.         s->Message(client, t, op, msg, n);
  396.     }
  397.     }
  398. }
  399.  
  400. /*
  401.  * Set up an additional channel to receive data on.  This channel
  402.  * is treated as a stream--no packet interpretation is performed.
  403.  * Note that AddChannel does not start listening to the channel--
  404.  * this must be done by Attach.
  405.  */
  406.  
  407. void ObjectSpace::AddChannel (int c, ObjectStub* o) {
  408.     register Stream* s;
  409.  
  410.     s = new Stream;
  411.     s->channel = c;
  412.     s->mask = (1 << c);
  413.     s->object = o;
  414.     s->next = streams;
  415.     streams = s;
  416. }
  417.  
  418. /*
  419.  * Remove a channel and stop listening to it.
  420.  */
  421.  
  422. void ObjectSpace::RemoveChannel (int c) {
  423.     register Stream* s, * prev;
  424.  
  425.     prev = nil;
  426.     for (s = streams; s != nil; s = s->next) {
  427.     if (s->channel == c) {
  428.         if (prev == nil) {
  429.         streams = s->next;
  430.         } else {
  431.         prev->next = s->next;
  432.         }
  433.         Detach(c);
  434.         delete s;
  435.         break;
  436.     }
  437.     prev = s;
  438.     }
  439. }
  440.  
  441. /*
  442.  * Change path in space manager.
  443.  */
  444.  
  445. void ObjectSpace::UsePath (const char* newpath) {
  446.     manager->UsePath(newpath);
  447. }
  448.  
  449. /*
  450.  * Create connection to an object space.
  451.  * Block if wait is true.
  452.  */
  453.  
  454. Connection* ObjectSpace::Find (const char* spacename, boolean wait) {
  455.     return manager->Find(spacename, wait);
  456. }
  457.  
  458. /*
  459.  * What to do if we get some message data that is intolerable.
  460.  */
  461.  
  462. static void BadMessage (int index) {
  463.     fprintf(stderr, "invalid buffer index %d\n", index);
  464.     exit(1);
  465. }
  466.  
  467. /*
  468.  * Initial and maximum allowed buffer sizes for a client.
  469.  * A client's buffer grows when an incoming packet is larger than
  470.  * the packet size.
  471.  */
  472.  
  473. static const int initlen = 256;
  474. static const int maxlen = 8192;
  475.  
  476. Messenger::Messenger (ObjectSpace* s, Connection* c) {
  477.     space = s;
  478.     client = c;
  479.     pending = false;
  480.     buffer = new char[initlen];
  481.     buflen = initlen;
  482.     cur = 0;
  483.     count = 0;
  484.     next = nil;
  485.     prev = nil;
  486. }
  487.  
  488. Messenger::~Messenger () {
  489.     delete client;
  490.     delete buffer;
  491. }
  492.  
  493. /*
  494.  * We have reached the head of the active queue, so try to read a message
  495.  * into our buffer and split it into packets.
  496.  */
  497.  
  498. MessengerState Messenger::Run () {
  499.     if (ProcessMessage()) {
  500.     return ready;
  501.     } else if (pending) {
  502.     return ReadData();
  503.     } else {
  504.     return waiting;
  505.     }
  506. }
  507.  
  508. /*
  509.  * Read as much data as we can into the buffer.
  510.  */
  511.  
  512. MessengerState Messenger::ReadData () {
  513.     register int n, last;
  514.  
  515.     last = cur + count;
  516.     if (last < 0 || last >= buflen) {
  517.     BadMessage(last);
  518.     }
  519.     n = client->Read(&buffer[last], buflen - last);
  520.     if (n > 0) {
  521.     count += n;
  522.     pending = false;
  523.     return ready;
  524.     } else {
  525.     if (n < 0) {
  526.         /* error reading data -- ignore for now */
  527.     }
  528.     return finished;
  529.     }
  530. }
  531.  
  532. /*
  533.  * Try to process a packet in the buffer.  If there isn't a complete one,
  534.  * return false.  Otherwise handle the packet and return true.
  535.  */
  536.  
  537. boolean Messenger::ProcessMessage () {
  538.     boolean b;
  539.     register Packet* h;
  540.     register int len, hlen;
  541.  
  542.     if (cur < 0 || cur >= buflen) {
  543.     BadMessage(cur);
  544.     }
  545.     if (count < sizeof(Packet)) {
  546.     /* incomplete packet header in buffer */
  547.     b = false;
  548.     } else {
  549.     h = (Packet*) &buffer[cur];
  550.     hlen = WordAlign(h->length);
  551.     len = sizeof(Packet) + hlen;
  552.     if (hlen > maxlen) {
  553.         /* bad length, skip over header */
  554.         b = true;
  555.         cur += sizeof(Packet);
  556.         count -= sizeof(Packet);
  557.         if (count == 0) {
  558.         cur = 0;
  559.         }
  560.     } else if (count < len) {
  561.         /* incomplete packet */
  562.         b = false;
  563.         if (len > buflen) {
  564.         GrowBuffer(len);
  565.         }
  566.     } else {
  567.         b = true;
  568.         cur += sizeof(Packet);
  569.         space->Deliver(client, h->tag, h->op, &buffer[cur], h->length);
  570.         count -= len;
  571.         if (count == 0) {
  572.         cur = 0;
  573.         } else {
  574.         cur += hlen;
  575.         }
  576.     }
  577.     }
  578.     if (!b && cur != 0) {
  579.     /* move incomplete message to beginning of buffer */
  580.     memmove(&buffer[0], &buffer[cur], count);
  581.     cur = 0;
  582.     }
  583.     return b;
  584. }
  585.  
  586. /*
  587.  * Grow the buffer to handle a larger message.
  588.  */
  589.  
  590. void Messenger::GrowBuffer (int len) {
  591.     char* overflow;
  592.  
  593.     overflow = new char[len];
  594.     memmove(&overflow[0], &buffer[cur], count);
  595.     cur = 0;
  596.     delete buffer;
  597.     buffer = overflow;
  598.     buflen = len;
  599. }
  600.